#include "ia32_types.h"
#ifndef __VMM_HEADER__
#define __VMM_HEADER__
struct SharedProcessorData {
	volatile long reference_count;  //!< Number of processors sharing this data
	void* msr_bitmap;               //!< Bitmap to activate MSR I/O VM-exit
	void* io_bitmap_a;              //!< Bitmap to activate IO VM-exit (~ 0x7FFF)
	void* io_bitmap_b;              //!< Bitmap to activate IO VM-exit (~ 0xffff)
};

struct HookPid;

struct HookPid {
	struct HookPid* pLast;
	struct HookPid* pNext;

	ULONG_PTR nPid;
};

struct SuperKillParam {
	PDEVICE_OBJECT pCurrentDeviceObject;
};

struct GpRegisters {
	ULONG_PTR r15;
	ULONG_PTR r14;
	ULONG_PTR r13;
	ULONG_PTR r12;
	ULONG_PTR r11;
	ULONG_PTR r10;
	ULONG_PTR r9;
	ULONG_PTR r8;
	ULONG_PTR di;
	ULONG_PTR si;
	ULONG_PTR bp;
	ULONG_PTR sp;
	ULONG_PTR bx;
	ULONG_PTR dx;
	ULONG_PTR cx;
	ULONG_PTR ax;
};

union FlagRegister {
	ULONG_PTR all;
	struct {
		ULONG_PTR cf : 1;          //!< [0] Carry flag
		ULONG_PTR reserved1 : 1;   //!< [1] Always 1
		ULONG_PTR pf : 1;          //!< [2] Parity flag
		ULONG_PTR reserved2 : 1;   //!< [3] Always 0
		ULONG_PTR af : 1;          //!< [4] Borrow flag
		ULONG_PTR reserved3 : 1;   //!< [5] Always 0
		ULONG_PTR zf : 1;          //!< [6] Zero flag
		ULONG_PTR sf : 1;          //!< [7] Sign flag
		ULONG_PTR tf : 1;          //!< [8] Trap flag
		ULONG_PTR intf : 1;        //!< [9] Interrupt flag
		ULONG_PTR df : 1;          //!< [10] Direction flag
		ULONG_PTR of : 1;          //!< [11] Overflow flag
		ULONG_PTR iopl : 2;        //!< [12:13] I/O privilege level
		ULONG_PTR nt : 1;          //!< [14] Nested task flag
		ULONG_PTR reserved4 : 1;   //!< [15] Always 0
		ULONG_PTR rf : 1;          //!< [16] Resume flag
		ULONG_PTR vm : 1;          //!< [17] Virtual 8086 mode
		ULONG_PTR ac : 1;          //!< [18] Alignment check
		ULONG_PTR vif : 1;         //!< [19] Virtual interrupt flag
		ULONG_PTR vip : 1;         //!< [20] Virtual interrupt pending
		ULONG_PTR id : 1;          //!< [21] Identification flag
		ULONG_PTR reserved5 : 10;  //!< [22:31] Always 0
	} fields;
};

/// Represents VMM related data associated with each processor
struct ProcessorData {
	SharedProcessorData* shared_data;         //!< Shared data
	void* vmm_stack_limit;                    //!< A head of VA for VMM stack
	struct VmControlStructure* vmxon_region;  //!< VA of a VMXON region
	struct VmControlStructure* vmcs_region;   //!< VA of a VMCS region
	struct EptData* ept_data;                 //!< A pointer to EPT related data
	struct _HOOK_EPT_STRUCT* pRing0HookData;
	struct _HOOK_EPT_STRUCT* pRing3HookData;
	struct HookPid* pFirstHookPid;
	void* pReadBuffer;
};

struct MachineFrame {
	ULONG_PTR ip;
	ULONG_PTR cs;
	ULONG_PTR flags;
	ULONG_PTR sp;
	ULONG_PTR ss;
};

struct VmmInitialStack {
	GpRegisters gp_regs;
	KtrapFrame trap_frame;
	ProcessorData* processor_data;
};

struct GuestContext {
	union {
		VmmInitialStack* stack;
		GpRegisters* gp_regs;
	};
	FlagRegister flag_reg;
	ULONG_PTR ip;
	ULONG_PTR cr8;
	KIRQL irql;
	bool vm_continue;
};

void VmmpInjectInterruption(InterruptionType interruption_type, InterruptionVector vector, bool deliver_error_code, ULONG32 error_code);
#endif